﻿using Newtonsoft.Json;
using RestSharp;
using RestSharp.Authenticators;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Ceri.Platform.EAM_NEW.API.Common.Helper
{
    /// <summary>
    /// httpclinet请求方式，请尽量使用IHttpClientFactory方式
    /// </summary>
    public class HttpHelper
    {
        public static async Task<string> GetAsync(string serviceAddress)
        {
            try
            {
                string result = string.Empty;
                Uri getUrl = new Uri(serviceAddress);
                using var httpClient = new HttpClient();
                httpClient.Timeout = new TimeSpan(0, 0, 60);
                result = await httpClient.GetAsync(serviceAddress).Result.Content.ReadAsStringAsync();
                return result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return null;
        }

        public static async Task<string> PostAsync(string serviceAddress, string requestJson = null)
        {
            try
            {
                string result = string.Empty;
                Uri postUrl = new Uri(serviceAddress);

                using (HttpContent httpContent = new StringContent(requestJson))
                {
                    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    using var httpClient = new HttpClient();
                    httpClient.Timeout = new TimeSpan(0, 0, 60);
                    result = await httpClient.PostAsync(serviceAddress, httpContent).Result.Content.ReadAsStringAsync();
                }
                return result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return null;
        }



        public class RestSharpClient : IRestSharp
        {
            /// <summary>
            /// 请求客户端
            /// </summary>
            private RestClient client;

            /// <summary>
            /// 接口基地址 
            /// </summary>
            private string BaseUrl { get; set; }

            /// <summary>
            /// 默认的时间参数格式
            /// </summary>
            private string DefaultDateParameterFormat { get; set; }

            /// <summary>
            /// 默认验证器
            /// </summary>
            private IAuthenticator DefaultAuthenticator { get; set; }

            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="baseUrl"></param>
            /// <param name="authenticator"></param>
            public RestSharpClient(string baseUrl, IAuthenticator authenticator = null)
            {
                BaseUrl = baseUrl;
                client = new RestClient(BaseUrl);
                DefaultAuthenticator = authenticator;

                //默认时间显示格式
                DefaultDateParameterFormat = "yyyy-MM-dd HH:mm:ss";

                //默认校验器
                if (DefaultAuthenticator != null)
                {
                    client.Authenticator = DefaultAuthenticator;
                }
            }

            /// <summary>
            /// 通用执行方法
            /// </summary>
            /// <param name="request">请求参数</param>
            /// <remarks>
            /// 调用实例：
            /// var client = new RestSharpClient("******/");
            /// var result = client.Execute(new RestRequest("v2/movie/in_theaters", Method.GET));
            /// var content = result.Content;//返回的字符串数据
            /// </remarks>
            /// <returns></returns>
            public IRestResponse Execute(IRestRequest request)
            {
                request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
                var response = client.Execute(request);
                return response;
            }

            /// <summary>
            /// 同步执行方法
            /// </summary>
            /// <typeparam name="T">返回的泛型对象</typeparam>
            /// <param name="request">请求参数</param>
            /// <remarks>
            ///  var client = new RestSharpClient("*****/");
            ///  var result = client.Execute<List<string>>(new RestRequest("v2/movie/in_theaters", Method.GET)); 
            /// </remarks>
            /// <returns></returns>
            public T Execute<T>(IRestRequest request) where T : new()
            {
                request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
                var response = client.Execute<T>(request);
                return response.Data;
            }

            /// <summary>
            /// 异步执行方法
            /// </summary>
            /// <param name="request">请求参数</param>
            /// <param name="callback">回调函数</param>
            /// <remarks>
            /// 调用实例：
            /// var client = new RestSharpClient("http://******/");
            /// client.ExecuteAsync<List<string>>(new RestRequest("v2/movie/in_theaters", Method.GET), result =>
            /// {
            ///      var content = result.Content;//返回的字符串数据
            /// });
            /// </remarks>
            /// <returns></returns>
            [Obsolete]
            public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback)
            {
                request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
                return client.ExecuteAsync(request, callback);
            }

            /// <summary>
            /// 异步执行方法
            /// </summary>
            /// <typeparam name="T">返回的泛型对象</typeparam>
            /// <param name="request">请求参数</param>
            /// <param name="callback">回调函数</param>
            /// <remarks>
            /// 调用实例：
            /// var client = new RestSharpClient("http://********/");
            /// client.ExecuteAsync<List<string>>(new RestRequest("v2/movie/in_theaters", Method.GET), result =>
            /// {
            ///      if (result.StatusCode != HttpStatusCode.OK)
            ///      {
            ///         return;
            ///      }
            ///      var data = result.Data;//返回数据
            /// });
            /// </remarks>
            /// <returns></returns>
            [Obsolete]
            public RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new()
            {
                request.DateFormat = string.IsNullOrEmpty(request.DateFormat) ? DefaultDateParameterFormat : request.DateFormat;
                return client.ExecuteAsync<T>(request, callback);
            }
        }

        /// <summary>
        /// Get 请求
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="baseUrl">根地址
        /// <param name="url">接口:api/xx/yy</param>
        /// <param name="pragm">参数:id=2&name=张三</param>
        /// <returns></returns>
        public static T GetApi<T>(string baseUrl, string url, string pragm = "")
        {
            var client = new RestSharpClient(baseUrl);

            var request = client.Execute(string.IsNullOrEmpty(pragm)
                ? new RestRequest(url, Method.GET)
                : new RestRequest($"{url}?{pragm}", Method.GET));

            if (request.StatusCode != HttpStatusCode.OK)
            {
                return (T)Convert.ChangeType(request.ErrorMessage, typeof(T));
            }


            JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
            //这一行就是设置Json.NET能够序列化接口或继承类的关键，将TypeNameHandling设置为All后，
            //Json.NET会在序列化后的json文本中附加一个属性说明json到底是从什么类序列化过来的，也可以设置TypeNameHandling为Auto，
            //表示让Json.NET自动判断是否需要在序列化后的json中添加类型属性，
            //如果序列化的对象类型和声明类型不一样的话Json.NET就会在json中添加类型属性，反之就不添加，
            //但是我发现TypeNameHandling.Auto有时候不太好用。。。
            jsonSerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
            //将JsonSerializerSettings作为参数传入反序列化函数，这样Json.NET就会读取json文本中的类型属性，知道应该反序列化成什么类型
            var a = JsonConvert.DeserializeObject<T>(request.Content, jsonSerializerSettings);

            //dynamic temp = JsonConvert.DeserializeObject(request.Content, typeof(T));

            //T result = (T)Convert.ChangeType(request.Content, typeof(T));

            return a;
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="url">完整的url</param>
        /// <param name="body">post body,可以匿名或者反序列化</param>
        /// <returns></returns>
        public static T PostApi<T>(string url, object body = null)
        {
            var client = new RestClient($"{url}");
            IRestRequest queest = new RestRequest();
            queest.Method = Method.POST;
            queest.AddHeader("Accept", "application/json");
            queest.AddParameter("application/json", body, ParameterType.RequestBody);
            //queest.AddJsonBody(body); // 可以使用 JsonSerializer
            var result = client.Execute(queest);
            if (result.StatusCode != HttpStatusCode.OK)
            {
                return (T)Convert.ChangeType(result.ErrorMessage, typeof(T));
            }



            dynamic temp = JsonConvert.DeserializeObject(result.Content, typeof(T));
            //T result = (T)Convert.ChangeType(request.Content, typeof(T));

            return (T)temp;
        }

    }

    public interface IRestSharp
    {
        /// <summary>
        /// 同步执行方法
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        IRestResponse Execute(IRestRequest request);

        /// <summary>
        /// 同步执行方法
        /// </summary>
        /// <typeparam name="T">返回值</typeparam>
        /// <param name="request">请求参数</param>
        /// <returns></returns>
        T Execute<T>(IRestRequest request) where T : new();

        /// <summary>
        /// 异步执行方法
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <param name="callback"></param>
        /// <returns></returns>
        RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action<IRestResponse> callback);

        /// <summary>
        /// 异步执行方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        RestRequestAsyncHandle ExecuteAsync<T>(IRestRequest request, Action<IRestResponse<T>> callback) where T : new();
    }


}
